/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nl.windesheim.archdemo.presentationmodel;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import java.util.Date;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import nl.windesheim.archdemo.dao.GlobalInstances;
import nl.windesheim.archdemo.dao.OrderDao;
import nl.windesheim.archdemo.model.Order;
import nl.windesheim.archdemo.view.EditOrderDialog;
import nl.windesheim.archdemo.view.MainFrame;
import nl.windesheim.archdemo.view.OkCancelDialog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;

/**
 *
 * @author reindert
 */
public class MainFramePresenter implements ListSelectionListener, ActionListener, WindowStateListener,
           ChangeListener {

    private MainFrame view;
    private OrderTablePresenter orderTablePresenter = new OrderTablePresenter();
    private OrderLineTablePresenter orderLineTablePresenter = new OrderLineTablePresenter();
    private OrderDao orderDao = GlobalInstances.getOrderDao();

    public void setView(MainFrame view) {
        this.view = view;

        view.getNewOrderButton().addActionListener(this);
        view.getEditOrderButton().addActionListener(this);

        JTable orderTable = view.getOrderTable();

        this.orderTablePresenter.setView(orderTable);

        orderTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        view.getOrderLineTable().getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        orderTablePresenter.addTableModelListener(orderTable);
        orderTable.getSelectionModel().addListSelectionListener(this);
        orderTable.changeSelection(0, 0, false, false);
    }

    /** Other order selected, update view */
    @Override
    public void valueChanged(ListSelectionEvent lse) {
        JTable orderTable = view.getOrderTable();
        if (lse.getSource() == orderTable.getSelectionModel()) {
            Order sel = this.orderTablePresenter.getRowModel(orderTable.getSelectedRow());
            if (sel != null) {
                ((OrderLineTablePresenter) this.orderLineTablePresenter).setOrder(sel);
            }
        }
    }

    /** Show new order dialog */
    @Override
    public void actionPerformed(ActionEvent ae) {
        if (ae.getActionCommand().equals("NewOrder")) {
            // FIXME: order creation should be in business layer
            Order newOrder = new Order();
            newOrder.setCreationDate(new Date());
            newOrder.setStatus("NEW");
            showEditOrderDialog(newOrder);
        } else if (ae.getActionCommand().equals("EditOrder")) {
            // FIXME: should be in business layer
            JTable orderTable = view.getOrderTable();
            Order sel = this.orderTablePresenter.getRowModel(orderTable.getSelectedRow());   
            showEditOrderDialog(sel);
        }
    }

    private void showEditOrderDialog(Order o) {
        EditOrderDialogPresenter pres = new EditOrderDialogPresenter(o);
        EditOrderDialog dialog = new EditOrderDialog(view, pres, false);
        pres.setView(dialog);
        // dialog is not modal so we cannot check here for return status,
        // have to use event
        pres.addChangeListener(this);
        dialog.addWindowStateListener(this);
        dialog.setVisible(true);
    }

    
    /** called after a editorderdialog is closed.
     * (multiple may be open at any time!!)
     * @param we 
     */
    @Override
    public void windowStateChanged(WindowEvent we) {
        if (we.getComponent() instanceof EditOrderDialog) {
            EditOrderDialog dialog = (EditOrderDialog) we.getComponent();
            if (dialog.getReturnStatus() == OkCancelDialog.RET_OK) {
                // don't make UI wait for db update
                java.awt.EventQueue.invokeLater(new SaveOrder(dialog.getModel().getOrder()));
            }
            orderTablePresenter.refresh();
            JTable orderTable = view.getOrderTable();
            Order sel = this.orderTablePresenter.getRowModel(orderTable.getSelectedRow()); 
            if(dialog.getModel().getOrder().getId() == sel.getId()){
                this.orderLineTablePresenter.refresh();
            }
        }
    }

    @Override
    /** Called whenever a value is edited on an order */
    public void stateChanged(ChangeEvent ce) {
        if (ce.getSource() instanceof EditOrderDialogPresenter) {
            orderTablePresenter.refresh();
            EditOrderDialogPresenter pres = (EditOrderDialogPresenter) ce.getSource();
            // update orderlinetable if order that was changed is current selection
            orderTablePresenter.refresh();
            JTable orderTable = view.getOrderTable();
            Order sel = this.orderTablePresenter.getRowModel(orderTable.getSelectedRow()); 
            if(pres.getOrder().getId() == sel.getId()){
                this.orderLineTablePresenter.refresh();
                //this.view.getOrderLineTable().updateUI();
            }
        }     
    }

    private class SaveOrder implements Runnable {

        private Order order;

        public SaveOrder(Order order) {
            this.order = order;
        }

        @Override
        public void run() {
            orderDao.save(order);
        }
    }

    public OrderLineTablePresenter getOrderLineTablePresenter() {
        return orderLineTablePresenter;
    }

    public OrderTablePresenter getOrderTablePresenter() {
        return orderTablePresenter;
    }
}
